package com.jszc.lottery.common.datatest.lambda;

import com.jszc.lottery.common.datatest.ArrayUtil;
import com.jszc.lottery.common.datatest.CommonException;

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created by Administrator on 2016/4/26.
 */
public class LambdaUtil {

    /**
     * demo样例
     */
    private void DEMO() {
        List<String> list = Arrays.asList("1", "2", "3");

        String ret = LambdaUtil.firstDefault(list, (s) -> s == "2", null);
        boolean ret1 = LambdaUtil.any(list, (s) -> s == "2");
        List<String> list1 = LambdaUtil.where(list, (e) -> e == "1" || e == "2");

//===================================group by(复制到test中执行) Start===================================
//        List<SysDicEntity> list = new ArrayList<SysDicEntity>();
//
//        for (int i = 0; i < 500; i++) {
//            SysDicEntity dic1 = new SysDicEntity();
//            dic1.setCode("code1");
//            dic1.setName("name" + i);
//            list.add(dic1);
//
//            SysDicEntity dic2 = new SysDicEntity();
//            dic2.setCode("code2");
//            dic2.setName("name" + i);
//            list.add(dic2);
//        }
//
//        // 进行分组
//        Map<String, List<SysDicEntity>> map = LambdaUtil.group(list, new LambdaUtil.GroupBy<String>() {
//            @Override
//            public String groupby(Object obj) {
//                SysDicEntity d = (SysDicEntity) obj;
//                // 返回值即为分组依据，可以组合多个字段进行分组
//                return d.getCode();
//            }
//        });
//
//        for (Map.Entry<String, List<SysDicEntity>> entry : map.entrySet()) {
//            String key = entry.getKey(); // 分组内容
//            List<SysDicEntity> entities = entry.getValue(); // 同组数据
//        }
//===================================group by(复制到test中执行) End===================================
    }

    /**
     * 遍历集合找到第一个匹配对象
     *
     * @param list   集合对象
     * @param p      匹配条件 可以采用 -> lambda 语法
     * @param defVal 如果没匹配采用的默认值 默认值
     * @param <T>
     * @return
     */
    public static <T> T firstDefault(Collection<T> list, Predicate<? super T> p, T defVal) {
        T t = defVal;
        if (ArrayUtil.isCollectionEmpty(list)) {
            return t;
        }
        for (T tt : list) {
            if (p.test(tt)) {
                t = tt;
                break;
            }
        }
        return t;
    }

    /**
     * 遍历集合是否存在匹配项
     */
    public static <T> boolean any(Collection<T> list, Predicate<? super T> p) {
        if (ArrayUtil.isCollectionEmpty(list)) {
            return false;
        }
        return list.stream().anyMatch(p);
    }

    /**
     * where 查询过滤语句
     */
    public static <T> List<T> where(Collection<T> list, Predicate<? super T> p) {
        if (ArrayUtil.isCollectionEmpty(list)) {
            return new LinkedList<T>();
        }
        return list.stream().filter(p).collect(Collectors.toList());
    }

    /**
     * 从对象集合中提炼属性集合
     */
    public static <T, R> List<R> select(Collection<T> list, Function<? super T, ? extends R> mapper) {
        if (ArrayUtil.isCollectionEmpty(list)) {
            return new ArrayList<R>();
        }
        return list.stream().map(mapper).collect(Collectors.toList());
    }

    /**
     * 获得空数组
     */
    public static <T> T[] getEmtptyArray(Class<T> cls) {
        return (T[]) Array.newInstance(cls, 0);
    }

    /**
     * 列表转化成数组
     */
    public static <T> T[] listToArray(Class<T> cls, Collection<T> list) {
        T[] arr = (T[]) Array.newInstance(cls, list.size());
        list.toArray(arr);
        return arr;
    }

    /**
     * 数组转化成列表
     */
    public static <T> List<T> arrayToList(Class<T> cls, T[] arr) {
        if (arr == null){
            return new ArrayList<T>();
        }
        return Arrays.asList(arr);
    }

    /**
     * 唯一化列表
     *
     * @param list
     * @param p
     * @param <T>
     * @return
     */
    public static <T> List<T> distinctList(List<T> list, IFunc2<T, T, Boolean> p) {
        if (ArrayUtil.isCollectionEmpty(list)) {
            return new LinkedList<T>();
        }
        List<T> tempList = new LinkedList<>();
        for (T t : list) {
            boolean exist = false;
            for (T e : tempList) {
                if (p.invoke(t, e)) {
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                tempList.add(t);
            }
        }
        return tempList;
    }

    /**
     * 分组依据接口，用于集合分组時，获取分组依据
     */
    public interface GroupBy<T> {
        T groupby(Object obj);
    }

    /**
     * 对集合进行分组
     *
     * @param colls 集合
     * @param gb    分组依据
     * @param <T>   分组依据的类型
     * @param <D>   集合的类型
     * @return 分组后的Map
     */
    public static final <T extends Comparable<T>, D> Map<T, List<D>> group(Collection<D> colls, GroupBy<T> gb) {
        if (colls == null || colls.isEmpty()) {
            throw new CommonException("分组集合不能为空!");
        }

        if (gb == null) {
            throw new CommonException("分组依据接口不能为null!");
        }

        Iterator<D> iter = colls.iterator();
        Map<T, List<D>> map = new HashMap<T, List<D>>();
        while (iter.hasNext()) {
            D d = iter.next();
            T t = gb.groupby(d);
            if (map.containsKey(t)) {
                map.get(t).add(d);
            } else {
                List<D> list = new ArrayList<D>();
                list.add(d);
                map.put(t, list);
            }
        }

        return map;
    }


    /**
     * 值合并 如果合并失败使用的defVal
     * 比如 在sum时用
     *
     * @param list
     * @param p
     * @param defVal
     * @param <T>
     */
    public static <T> T valMerge(List<T> list, IFunc2<T, T, T> p, T defVal) {
        if (ArrayUtil.isCollectionEmpty(list)) {
            return defVal;
        }
        T mergeT = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            mergeT = p.invoke(mergeT, list.get(i));
        }
        return mergeT;
    }
}
